
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

using Swaf;
using Swaf.BizObj;
using Swaf.BizRule;
using Swaf.Container;
using Swaf.Logging;

namespace Swaf.Gui.AspNet2
{
    /// <summary>
    /// 
    /// </summary>
    public class AspNetGlobal : System.Web.HttpApplication
    {
		protected bool m_usingCompanyUrl = false;
		
		/// <summary>Starts the Swaf framework application via the static
        /// Swaf.Application.create method.  Note that the application can be started 
        /// with the bizrules running within the web tier or with the bizrules running as 
        /// a seperate middle tier.
        /// </summary>
        public virtual void Application_Start(object sender, EventArgs e)
        {
            string baseLoc = @"file://" + Server.MapPath("~/.");
            //Uncomment the configLoc below for a seperate web tier/middle tier distribution.
            //Note that in order for this to work, the middle tier services must be present.

            string configLoc = baseLoc + Cmn.callPropertyGet(this, "AppConfigFileName");

			Swaf.Application.create(configLoc, baseLoc, Server.MapPath("~/."));
            Swaf.Application.globalApp.appData.put("baseDir", Server.MapPath("~"));
        }

        public virtual void Application_End(object sender, EventArgs e)
        {
            IAppManagement mngt = (IAppManagement)Swaf.Application.globalApp;
            mngt.shutdown();
        }

        public virtual void Session_Start(object sender, EventArgs e)
        {
			Dictionary<string,bool> sessionKeys = new Dictionary<string,bool>();
			Session["SesKeys"] = sessionKeys;
			IAppManagement mngt = (IAppManagement)Swaf.Application.globalApp;
			IDictionary d = new Hashtable();
			d["firstUrl"] = Request.Url;
            BrowserBrand bb = BrowserBrand.Other;
            if (Request.Browser.Browser.ToUpper().IndexOf("IE") != -1)
                bb = BrowserBrand.IE;
            d["browserBrand"] = bb;
            d["userIP"] = Request.UserHostAddress;
            d["browserInfo"] = Request.UserAgent;
			string ourSessionId = Session.SessionID + getCurrentCompanyShortName();
            IApplication app = mngt.createSessionApplication(ourSessionId, false, d);			

        }

        public virtual void Session_End(object sender, EventArgs e)
        {
            // Note: The Session_End event is raised only when the sessionstate mode
            // is set to InProc in the Web.config file. If session mode is set to StateServer 
            // or SQLServer, the event is not raised.
            IAppManagement mngt = (IAppManagement)Swaf.Application.globalApp;
			Dictionary<string, bool> sessionKeys = (Dictionary<string, bool>)Session["SesKeys"];
			foreach (string key in sessionKeys.Keys)
			{
				try
				{
					IApplication app = ((IAppManagement)Swaf.Application.globalApp).createSessionApplication(key);
					app.ruleMgr.execute("updateSessionState", false);
				}
				catch (Exception)
				{
				}

				mngt.appSessionComplete(key);
			}
        }

        /// <summary>Connectiosn Swaf.Application.currentApp to the right session application
        /// based on the ASP.NET session being used by the browser sending the page requests.
        /// </summary>
        /// <remarks>Because this method is called several times without the ASP.NET session object
        /// setup properly, it uses the Request["ASP.NET_SessionId"] value to get the correct
        /// Swaf SessionApplication.</remarks>
        public virtual void Application_PostAcquireRequestState(object sender, EventArgs e)
        {
            string sessionId = Request["ASP.NET_SessionId"];
			if (sessionId == null && System.Web.HttpContext.Current.Session != null)
				sessionId = Session.SessionID;
			if (sessionId != null && sessionId != "" && Swaf.Application.globalApp != null && System.Web.HttpContext.Current.Session != null)
            {
				//string key = getCurrentCompanyShortName();
				string key = null;
				IResults rc = Swaf.Application.globalApp.ruleMgr.execute("getCompanyFromDomainName", Request.Url);
				CompanyDomainInfo companyInfo = rc.CallResults as CompanyDomainInfo;
				IBizObj company = companyInfo.Company;
				if (company != null && !Request.Url.PathAndQuery.StartsWith("/captcha") && !Request.Url.PathAndQuery.StartsWith("/fckeditor"))
					key = (string)company.get("shortName");
				else
				{
					if (Session["lastCompany"] == null)
						key = "";
					else
						key = (string)Session["lastCompany"];
				}

				//Doing this because fckeditor can have plugins that have aspx for js files and we need to know the company for it to hook up right.
				Session["lastCompany"] = key;

				string ourSesKey = Session.SessionID + key;
				Dictionary<string, bool> sessionKeys = (Dictionary<string, bool>)Session["SesKeys"];
				sessionKeys[ourSesKey] = true;
				IDictionary d = null;
				bool newSwafSession = false;
				if (!(Session[ourSesKey] is bool))
				{
					newSwafSession = true;
					d = new Hashtable();
					d["firstUrl"] = Request.Url;
					Session[ourSesKey] = true;
                    BrowserBrand bb = BrowserBrand.Other;
                    if (Request.Browser.Browser.ToUpper().IndexOf("IE") != -1)
                        bb = BrowserBrand.IE;
                    d["browserBrand"] = bb;
                    if (Request.UrlReferrer != null)
                        d["referrer"] = Request.UrlReferrer.OriginalString;
                    else
                        d["referrer"] = "";
					if (company != null)
						d["companyId"] = company.get("id");
					Swaf.Application.globalApp.Log.println(LoggingLevels.Medium, "Starting new session:{0}", ourSesKey);
				}
                IApplication app = Swaf.Application.currentApp = ((IAppManagement)Swaf.Application.globalApp).
					createSessionApplication(ourSesKey, false, d);
				if (newSwafSession)
				{
					//Code to setup SWAF session info in session state table

					FlexiMap m = new FlexiMap();
					m["sessionId"] = ourSesKey;
					IBizObj stateInfo = app.appData.get("DA.Syrinx.GetSessionState", m) as IBizObj;
					if (stateInfo != null)
					{
						//This indicates a user is browsing the site after their session ended and we will get it
						//back from the session state table.
						using (MemoryStream ms = new MemoryStream((byte[])stateInfo.get("sessionState")))
						{
							IMap sessionState = new BinaryFormatter().Deserialize(ms) as IMap;
							if (sessionState != null)
							{
								object x = sessionState.get("testval");
								((SessionApp)app).setSessionData(sessionState);
							}
							IBizObj user = app.bizObjMgr.create("User");
							user.put("userName", stateInfo.get("userName"));
							app.ruleMgr.execute("loginUserAdvanced", user, true);
						}
					}
					else
						app.ruleMgr.execute("updateSessionState", true);
				}
					
				//Swaf.Application.currentApp.sessionData["usingCompanyUrl"] = m_usingCompanyUrl;
				if (m_usingCompanyUrl)
				{
					m_usingCompanyUrl = false;
					Swaf.Application.currentApp.sessionData["usingCompanyUrl"] = true;
				}
				else
					Swaf.Application.currentApp.sessionData["usingCompanyUrl"] = false;
                // Allow derived classes additional setup
                sessionAppEstablished();
            }
        }

		protected string getCurrentCompanyShortName()
		{
			string companyId = "";
			string path = Request.Url.PathAndQuery;
			int	inx = path.IndexOf("/", 1);
				if (inx != -1)
					companyId = path.Substring(1, inx - 1);

			if (companyId.Length != -1 && (inx = path.IndexOf("pi=")) != -1)
			{
				int inx2 = companyId.LastIndexOf('=');
				if (inx2 != -1)
					companyId = companyId.Substring(inx2 + 1);
			}
			if (companyId.Length != 0)
			{
				IBizObj company = Swaf.Application.globalApp.ruleMgr.execute("getCompanyByShortName", companyId).CallResults as IBizObj;
				if (company == null)
				{
					if (Session["lastCompany"] == null)
						companyId = "";
					else
						companyId = (string)Session["lastCompany"];
				}
			}
			//Doing this because fckeditor can have plugins that have aspx for js files and we need to know the company for it to hook up right.
			Session["lastCompany"] = companyId;

			return companyId.ToLower();
		}

        protected virtual void sessionAppEstablished()
        {
            // Allow derived class to do additional functionality
        }
    }

    public enum BrowserBrand { IE, FireFox, Safari, Chrome, Other };
}
